// 实用程序类型
type User = {
  id?: number | undefined;
  name: string;
  email: string;
  password: string;
};

type PartialUser = Partial<User>;

/**
 * Partial
 * Partial<T> 可以用来描述一个具有 T 类型所有属性的对象，但这些属性都是 "可选" 的，可以不提供或者设置为 undefined
 * */
function removeEmptyProperties<T extends object>(obj: T): Partial<T> {
  return obj;
}
const result4 = removeEmptyProperties({
  name: "hello",
  age: 10,
  nestedObj: {
    a: 1,
  },
});
result4.nestedObj?.a;

/**
 * Required
 * Required<T> 可以用来描述一个具有 T 类型所有属性的对象，但这些属性都是必须提供的，不能为 undefined
 */
type RequiredUser = Required<PartialUser>;

/**
 * Omit
 * Omit<T, K> 可以用来描述一个具有 T 类型所有属性的对象，但排除了属性集合 K 中指定的属性。这样生成的新类型中将不包含属性集合 K 中指定的属性
 */
type UserWithoutPassword = Omit<User, "password" | "email">;

// Pick,从User中选择你需要的 name和id
type UserWithIdAndName = Pick<User, "name" | "id">;

// Record约定对象中key和value的类型，两种写法如下
type SomeObject1 = Record<string, boolean>;
type SomeObject2 = {
  [k: string]: boolean;
};

const test: SomeObject2 = {
  a: true,
};

export {};
